/**
 * 判断字符是否为空
 * @param {String} str 字符
 * @returns {Boolean}
 * 使用示例：isEmpty(' 222') false
 */
export function isEmpty(str) {
	try {
		return str.trim().length == 0
	} catch (e) {
		return true;
	}
}
/**
 * 计算字符的字节数
 * @param {Object} str 字符串
 * @returns {Number}
 * 使用示例：bytesLength('123') 3
 */
export function bytesLength(str) {
	if(!str) return 0;
	var c = str.match(/[^x00-xff]/ig);
	return str.length + (c == null ? 0 : c.length);
}
/**
 * 根据字节数获取字符串
 * @param {String} str 字符串
 * @param {Number} len 截取长度
 * @returns {Object} 截取后的字符串及是否截取的标记（扩展用）code=1 字符串截断   code=0  字符串未截断
 */
export function cutStrByte(str, len) {
	//校验参数
	if (!str || !len) {
		return { "cutStr": "", "code": 0 };
	}
	var code = "1", // 默认返回code值，已截断
		strLen = str.length, // 原字符串长度
		cutStr;
	//如果字符串长度小于截取长度的一半,则返回全部字符串
	if (strLen <= len / 2) {
		cutStr = str;
		code = "0";
	} else {
		//遍历字符串
		var strByteCount = 0;
		for (var i = 0; i < strLen; i++) {
			//中文字符字节加2  否则加1
			strByteCount += bytesLength(str.charAt(i));
			//i从0开始 截断时大于len 只截断到第i个
			if (strByteCount > len) {
				cutStr = str.substring(0, i);
				break;
			} else if (strByteCount == len) {
				cutStr = str.substring(0, i + 1);
				break;
			}
		}
	}
	//cutstr为空，没有截断字符串
	if (!cutStr) {
		cutStr = str;
		code = "0";
	}
	return { "cutStr": cutStr, "code": code };
}
/**
 * 字符串去掉换行符和空格
 * @param {String} str
 * @returns {String}
 * removeSpace('哈哈   嘻嘻')
 */
export function removeSpace(str) {
	let result = str.replace(/\s+/g, ""); // 去掉空格
	result = result.replace(/[\r\n]/g, ""); // 去掉换
	return result;
}
/**
 * 递归方式深拷贝数据
 * @param {Object|Array} source 需要拷贝的对象
 * @returns {Object|Array}
 * 使用示例：deepClone([1,2,3,4])
 */
export function deepClone(source) {
	if (!source && typeof source !== 'object') {
		throw new Error('error arguments', 'deepClone')
	}
	const targetObj = source.constructor === Array ? [] : {}
	Object.keys(source).forEach(keys => {
		if (source[keys] && typeof source[keys] === 'object') {
			targetObj[keys] = deepClone(source[keys])
		} else {
			targetObj[keys] = source[keys]
		}
	})
	return targetObj
}
/**
 * 数组根据某个字段进行排序
 * @param {Array} arr 数组
 * @param {String} k 字符串
 * @param {Boolean} up 是否正序 默认true
 * @returns {Array}
 * 使用示例：sort([{a:1},{a:3},{2},{a:0}],'a',false)
 */
export function sort(arr, k, up = true) {
	if (!Array.isArray(arr)) {
		throw new Error('数据类型必须是数组');
	}
	return arr.sort(compare(k, up));
}
/**
 * 为了满足数组根据某个字段进行排序
 * @param {*} k 数组关键词 
 * @param {*} up 是否是正序 默认true
 */
export function compare(k, up = true) {
	return function(a, b) {
		var v1 = a[k];
		var v2 = b[k];
		return up ? v1 - v2 : v2 - v1;
	}
}
/**
 * 根据对象用&拼接返回
 * @param {Object} json 对象
 * @returns {String}
 * 使用示例：param({a:1,b:2}) 返回：a=1&b=2
 */
export function param(json) {
	if (!json) return ''
	let newjson = Object.keys(json).map(key => {
		if (json[key] === undefined) return ''
		return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
	})
	return newjson.join('&');
}
/**
 * 根据时间戳+随机数生成32进制的字符串
 * @returns {string}
 * 使用示例：createUniqueString()
 */
export function createUniqueString() {
	const timestamp = +new Date() + ''
	const randomNum = parseInt((1 + Math.random()) * 65536) + ''
	return (+(randomNum + timestamp)).toString(32)
}
/**
 * 根据地址栏返回参数对象
 * @param {string} url 地址 非必传
 * @returns {Object}
 * getQueryObject('http://localhost:8080/demo#/demo?id=1&ff=2233'); 返回：{id: '1', ff: '2233'}
 */
export function getQueryObject(url) {
	url = url == null ? window.location.href : url
	const search = url.substring(url.lastIndexOf('?') + 1)
	const obj = {}
	const reg = /([^?&=]+)=([^?&=]*)/g
	search.replace(reg, (rs, $1, $2) => {
		const name = decodeURIComponent($1)
		let val = decodeURIComponent($2)
		val = String(val)
		obj[name] = val
		return rs
	})
	return obj
}
/**
 * 防抖
 * @param {Function} fn 回调函数
 * @param {number} dealy 等待时间
 * */
export function debounce(fn, dealy) {
	let timer = null;
	return function() {
		if (timer) {
			clearTimeout(timer)
		}
		timer = setTimeout(fn, dealy)
	}
}
/**
 * 节流
 * @param {Function} fn 回调函数
 * @param {number} dealy 等待时间
 * */
export function throttle(fn, dealy) {
	let flag = true;
	return function() {
		if (!flag) {
			return false;
		}
		flag = false;
		setTimeout(() => {
			fn();
			flag = true;
		}, dealy)
	}
}
/**
 * 数组去重
 * @param {Object} array 数组
 * @returns {Array}
 * 使用示例：removeRepeat([1,2,3,4,1,1]);返回[1,2,3,4]
 */
export function removeRepeat(array) {
	return Array.from(new Set(array));
}
/**
 * 字符串去掉转移符号
 * @param {Object} str
 * @returns {String}
 * 使用示例：removeSymbol('gdhjk\b')
 */
export function removeSymbol(str) {
	return str.replace(/[\'\"\\\/\b\f\n\r\t]/g, '');
}
/**
 * Merges two objects, giving the last one precedence
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 * 使用示例：objectMerge({a:1},{b:2});返回:{a:1,b:2}
 */
export function objectMerge(target, source) {
	if (typeof target !== 'object') {
		target = {}
	}
	if (Array.isArray(source)) {
		return source.slice()
	}
	Object.keys(source).forEach(property => {
		const sourceProperty = source[property]
		if (typeof sourceProperty === 'object') {
			target[property] = objectMerge(target[property], sourceProperty)
		} else {
			target[property] = sourceProperty
		}
	})
	return target
}
// =============时间相关=================
/**
 * Parse the time to string 处理时间 自定义返回形式
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string | null}
 * 使用示例：parseTime(new Date(),'{y}-{m}-{d} {h}:{i}:{s} 今天是星期{a}'); 返回：2021-10-15 17:52:38 今天是星期五
 */
export function parseTime(time, cFormat) {
	if (arguments.length === 0 || !time) {
		return null
	}
	const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
	let date
	if (typeof time === 'object') {
		date = time
	} else {
		if ((typeof time === 'string')) {
			if ((/^[0-9]+$/.test(time))) {
				// support "1548221490638"
				time = parseInt(time)
			} else {
				// support safari
				// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
				time = time.replace(new RegExp(/-/gm), '/')
			}
		}
		if ((typeof time === 'number') && (time.toString().length === 10)) {
			time = time * 1000
		}
		date = new Date(time)
	}
	const formatObj = {
		y: date.getFullYear(),
		m: date.getMonth() + 1,
		d: date.getDate(),
		h: date.getHours(),
		i: date.getMinutes(),
		s: date.getSeconds(),
		a: date.getDay()
	}
	const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
		const value = formatObj[key]
		// Note: getDay() returns 0 on Sunday
		if (key === 'a') {
			return ['日', '一', '二', '三', '四', '五', '六'][value]
		}
		return value.toString().padStart(2, '0')
	})
	return time_str
}
/**
 * 获取当天时间段
 * @returns {Array}
 * 使用示例：getCurrentDay();返回：["2020-05-20 00:00:00", "2020-5-20 23:59:59"]
 */
export function getCurrentDay() {
	var date = new Date();
	let year = date.getFullYear();
	let month = ((date.getMonth() + 1) < 10 ? "0" + (date.getMonth() + 1) : (date.getMonth() + 1));
	let day = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate());
	var startTime = year + "-" + month + "-" + day + " " + "00:00:00";
	var endTime = year + '-' + month + '-' + day + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
	return [startTime, endTime]
}
/**
 * 获取时间段相隔的小时数
 * @param {string} time1 第1个时间
 * @param {string} time2 第2个时间
 * @returns {Number}
 */
export function timeRangeHour(time1, time2) {
	let usedTime = new Date(time2).getTime() - new Date(time1).getTime();
	return (Math.ceil((usedTime / 1000) / 60) / 60);
}
/**
 * 倒计时
 * @param {Object} time 秒
 * @param {Object} fn 回调函数
 * @returns {Number}
 * 使用示例：countdown(60,(s)=>{console.log(s)}); 返回秒
 */
export function countdown(time = 10, fn) {
	let _t = time,
		_timer = null;
	if (fn) fn(_t);
	_timer = setInterval(() => {
		_t--;
		if (fn) fn(_t);
		if (_t <= 0) {
			clearInterval(_timer);
		}
	}, 1000)
}
/**
 * 判断是否是函数
 * @param {Object} val 值
 * @returns {Boolean}
 */
export function isFunction(val) {
	return typeof val === 'function';
}
/**
 * 设置缓存 (单位为秒)
 * @param {Object|Number|String} value 值
 * @param {String} key 设置缓存的关键词
 * @param {String} dateStamp 时间戳
 */
export const setStorage = (value, key = ACCESS_TOKEN, dateStamp = null) => {
	const params = {
		date: dateStamp ? dateStamp : new Date().getTime(),
		value
	};
	wx.setStorageSync(key, JSON.stringify(params));
}
/**
 * 获取缓存
 * @param {*} day 天数 1代表24小时
 * @param {*} key 获取缓存的关键词
 */
export const getStorage = (day = 1, key = ACCESS_TOKEN) => {
	let obj = wx.getStorageSync(key);
	if (!obj) return null;
	obj = JSON.parse(obj);
	const date = new Date().getTime();
	if (date - obj.date > 24 * 60 * 60 * 1000 * day) return null;
	return obj.value;
}
/**
 * 清除缓存
 * @param {*} key 清除缓存的关键词
 */
export const removeStorage = (key = ACCESS_TOKEN) => {
	wx.removeStorageSync(key);
}
/**
 * 图片转换成base64
 * @param {*} url 图片地址
 * @param {*} prefix 是否拼接前缀 默认true
 */
export function imgUrlToBase64(url, prefix = true) {
	return new Promise((reslove) => {
		if (!url) return reslove({
			code: -1,
			msg: '需要传入图片地址'
		});
		// #ifdef MP-WEIXIN
		uni.getFileSystemManager().readFile({
			filePath: url,
			encoding: 'base64',
			success: res => {
				let base64 = prefix ? 'data:image/jpeg;base64,' + res.data : res.data;
				reslove({
					code: 0,
					msg: '转换成功',
					data: base64
				});
			},
			fail: (e) => {
				reslove({
					code: -1,
					msg: `图片转换失败：${JSON.stringify(e)}`
				});
			}
		})
		// #endif
		// #ifdef H5
		uni.request({
			url: url,
			method: 'GET',
			responseType: 'arraybuffer',
			success: ress => {
				let base64 = uni.arrayBufferToBase64(ress.data); //把arraybuffer转成base64
				base64 = prefix ? 'data:image/jpeg;base64,' + base64 : base64;
				reslove({
					code: 0,
					msg: '转换成功',
					data: base64
				});
			},
			fail: (e) => {
				reslove({
					code: -1,
					msg: `图片转换失败：${JSON.stringify(e)}`
				});
			}
		})
		// #endif
		// #ifdef APP-PLUS
		plus.io.resolveLocalFileSystemURL(url, (entry) => {
			// 可通过entry对象操作test.html文件 
			entry.file((file) => {
				let fileReader = new plus.io.FileReader();
				fileReader.onloadend = (evt) => {
					const base64 = evt.target.result.substr(22);
					reslove({
						code: 0,
						msg: '转换成功',
						data: base64
					});
				}
				fileReader.readAsDataURL(file);
			});
		}, (e) => {
			reslove({
				code: -1,
				msg: `图片转换失败：${JSON.stringify(e)}`
			});
		});
		// #endif
	})
}
